<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<style>
  @keyframes elastic-grow {
    from {
      transform: scale(0);
    }
    70% {
      transform: scale(1.1);
      animation-timing-function: cubic-bezier(.1, .25, 1, .25);
      /* 反向的ease */
    }
  }
  
  input:not(:focus)+.callout {
    transform: scale(0);
  }
  
  input:focus+.callout {
    animation: elastic-grow .5s;
  }
  
  .callout {
    transform-origin: 1.4em -.4em;
  }
  /*input:not(:focus) + .callout { transform: scale(0); }
.callout {
transform-origin: 1.4em -.4em;
transition: .5s cubic-bezier(.25,.1,.3,1.5);
}*/
  /*不过也别灰心，因为修复这个问题不过是多加一行代码而已。假设我们
只想给提示框的关闭过程指定普通的ease 调速函数，那么可以在定义关闭
状态的CSS 规则中把当前的调速函数覆盖掉：*/
  /*input:not(:focus) + .callout {
transform: scale(0);
transition-timing-function: ease;
}*/
  /*为避免不小心对颜色设置了弹性过渡，可以尝试把过渡的作用范围
限制在某几种特定的属性上，而不是像以前那样什么都不指定。当我们在
transition 简写属性中不指定任何属性时，transition-property 就会得
到它的初始值：all。这意味着只要是可以过渡的属性，都会参与过渡。因
此，如果我们以后在提示框打开状态的样式规则中增加一行background 声
明，那么弹性过渡也会作用在这个属性上。所以最终完美版的代码应该是这
样的：*/
  /*
说到把过渡的作用范围限制
在特定属性上，你甚至可以通过
transition-delay 属性把各个
属性的过渡过程排成列队，这个
属性的值实际上就是transition
简写属性中的第二个时间值。举
例来说， 如果width 和height
都需要过渡效果，而且你希望高
度先变化然后宽度再变化（很
多弹出框脚本库已经把这种动画
效果推广开来了），就可以这样
写：transition: .5s height,
.8s .5s width;（ 也就是说，
让width 过渡的延时正好等于
height 过渡的持续时间）。*/
</style>

<body>
  <label>
  Your username: 
  <input id="username" />
  <span class="callout">Only letters, numbers,
  underscores (_) and hyphens (-) allowed!</span>
  </label>
</body>

</html>